/**
 * 文件名: curlHelper.cpp
 * 平台: Linux
 * 作者: Blxt
 * 描述:
 *  - curl辅助工具类,实现简单的 http Post和Get接口请求.
 * 时间: 20230504 13:36
 */
#include "curlHelper.h"
#include<string.h>

#define MAX_KB 1024
#define MAXN 1024 * MAX_KB

UCHAR buf[MAXN];

const char* MAP_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

/**
 * POST接口请求
 * @param urlStr       url
 * @param heads        请求头
 * @param strMsgBody   请求消息体
 * @param function     回调函数
 * @return
 */
CURLcode curlPostData(char* urlStr, char* heads, char* strMsgBody, size_t(*function)(void* buffer, size_t size, size_t nmemb)) {

	CURL* hnd = curl_easy_init();
	curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
	curl_easy_setopt(hnd, CURLOPT_URL, urlStr);
	curl_easy_setopt(hnd, CURLOPT_POST, 1); // post req   
	curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, false);
	curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYHOST, false);
	curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, function);	//对返回的数据进行操作的函数地址
	curl_easy_setopt(hnd, CURLOPT_WRITEDATA, NULL);					//这是HttpsReturnMsg的第四个参数值

	curl_easy_setopt(hnd, CURLOPT_FOLLOWLOCATION, 1L);

	// 头
	struct curl_slist* headers = NULL;
	headers = curl_slist_append(headers, "content-type: application/json");
	if (heads != NULL) {
		curl_slist_append(headers, heads);
	}
	curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
	// 数据
	curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, strMsgBody);

	CURLcode ret = curl_easy_perform(hnd);
	curl_easy_cleanup(hnd);
	return ret;
}

/**
 * GET接口请求
 * @param urlStr       url
 * @param heads        请求头
 * @param strMsgBody   请求消息体
 * @param function     回调函数
 * @return
 */
CURLcode curlGetData(char* urlStr, char* heads, char* strMsgBody, size_t(*function)(void* buffer, size_t size, size_t nmemb)) {

	CURL* hnd = curl_easy_init();
	curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "GET");
	curl_easy_setopt(hnd, CURLOPT_URL, urlStr);
	curl_easy_setopt(hnd, CURLOPT_POST, 1); // post req   
	curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, false);
	curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYHOST, false);
	curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, function);	//对返回的数据进行操作的函数地址
	curl_easy_setopt(hnd, CURLOPT_WRITEDATA, NULL);					//这是HttpsReturnMsg的第四个参数值

	curl_easy_setopt(hnd, CURLOPT_FOLLOWLOCATION, 1L);

	// 头
	struct curl_slist* headers = NULL;
	headers = curl_slist_append(headers, "content-type: application/json");
	if (heads != NULL) {
		curl_slist_append(headers, heads);
	}
	curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
	// 数据
	curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, strMsgBody);

	CURLcode ret = curl_easy_perform(hnd);
	curl_easy_cleanup(hnd);
	return ret;
}

/**
 * 图片转base64
 * @param imgPath  图片路径
 * @return base64字符串
 */
char* parseBase64(const char* imgPath)
{
	FILE* p = fopen(imgPath, "rb");
	// UCHAR buf[MAXN];
	int len = fread(buf, sizeof(unsigned char), MAXN, p);
#ifdef DEBUG
	printf("共读取%d个字节.\n", len);
	printf("16进制码:\n");
	for (int i = 0; i < len; i++)
	{
		if (i != 0 && i % 24 == 0) printf("\n");
		printf("%02x ", buf[i]);
	}
	printf("\n");
#endif // DEBUG
	fclose(p);
	int base64_len = len / 3 * 4 + (len % 3 != 0) * 4 + 1;
	char* base64 = new char[base64_len];
	memset(base64, '\0', sizeof(char) * base64_len);
	base64Encode(buf, len, base64);
	return base64;
}

void base64Encode(UCHAR* buf, int buf_size, char* base64)
{
#ifdef DEBUG
	printf("----------------------------------------------------\n");
	printf("buf-size = %d\n", buf_size);
#endif // DEBUG
	UCHAR tmp[3];
	int i;
	for (i = 0; i < buf_size / 3; i++)
	{
		tmp[0] = buf[i * 3];
		tmp[1] = buf[i * 3 + 1];
		tmp[2] = buf[i * 3 + 2];
		base64[i * 4] = MAP_TABLE[tmp[0] >> 2];
		base64[i * 4 + 1] = MAP_TABLE[(tmp[0] << 4 | tmp[1] >> 4) & 0x3F];
		base64[i * 4 + 2] = MAP_TABLE[(tmp[1] << 2 | tmp[2] >> 6) & 0x3F];
		base64[i * 4 + 3] = MAP_TABLE[tmp[2] & 0x3F];
#ifdef DEBUG
		printf("buf data : %x %x %x\n", tmp[0], tmp[1], tmp[2]);
		printf("=> %c%c%c%c\n", base64[i * 4], base64[i * 4 + 1], base64[i * 4 + 2], base64[i * 4 + 3]);
#endif // DEBUG
	}
	if (buf_size % 3 == 2)
	{
		tmp[0] = buf[i * 3];
		tmp[1] = buf[i * 3 + 1];
		base64[i * 4] = MAP_TABLE[tmp[0] >> 2];
		base64[i * 4 + 1] = MAP_TABLE[(tmp[0] << 4 | tmp[1] >> 4) & 0x3F];
		base64[i * 4 + 2] = MAP_TABLE[(tmp[1] << 2) & 0x3F];
		base64[i * 4 + 3] = '=';
	}
	else if (buf_size % 3 == 1)
	{
		tmp[0] = buf[i * 3];
		base64[i * 4] = MAP_TABLE[tmp[0] >> 2];
		base64[i * 4 + 1] = MAP_TABLE[(tmp[0] << 4) & 0x3F];
		base64[i * 4 + 2] = '=';
		base64[i * 4 + 3] = '=';
	}
#ifdef DEBUG
	printf("----------------------------------------------------\n");
#endif // DEBUG
	}